<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>模拟实现new</title>
</head>

<body>
  <script>
    // 1.新建一个对象
    // 2.取出第一个参数，即传入的构造函数
    // 3.将obj的原型指向构造函数，使obj可以访问构造函数原型中的属性
    // 4.使用apply，改变构造函数this的指向到新建的对象
    // 5.如果构造函数有返回值且返回志是一个对象，则返回这个对象，否则返回obj

    function _new() {
      var obj = new Object() //新建一个对象

      var Constructor = [].shift.call(arguments); //取得外部传入的构造器，shift会修改数组，arguments会被去除第一个参数

      obj.__proto__ = Constructor.prototype // 将obj的原型指向构造函数

      var ret = Constructor.apply(obj, arguments); // 改变构造函数this的指向到新建的对象

      return typeof ret === 'object' ? ret || obj : obj; // 确保构造器总是返回一个对象

    };

    // test
    function Person(name, age) {
      this.name = name
      this.age = age
      this.hobby = 'coding'
      // return {
      //   name: name,
      //   hobby: 'coding'
      // }
    }
    Person.prototype.strength = 60
    Person.prototype.sayYourName = function () {
      console.log('I am ' + this.name)
    }
    // var Jqq = new Person('jqq', 18)
    var Jqq = _new(Person, 'jqq', 18)
    console.log(Jqq.name, Jqq.hobby, Jqq.strength)
    Jqq.sayYourName()
  </script>
</body>

</html>